package jcu.salt.io;

import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;

import jcu.sal.common.Response;

/**
 * TransmissionOutputStream
 * 
 * This stream is able to receive a instance of class
 * Transmitable and encodes this into gzipped XML before 
 * handing over to the connected output stream.
 * 
 * @see Transmittable 
 *
 */
public class TransmissionOutputStream extends DataOutputStream {

	private BufferedOutputStream bufout = null;
	private GZIPOutputStream gzipout = null;		
	private XMLEncoder xmlenc = null;
	private ObjectOutputStream oout;
		
	/**
	 * Initializes the stream with the given OutputStream as
	 * destination using xml encoding and gzipped transmission.
	 * 
	 * @param out destination
	 */
	public TransmissionOutputStream(OutputStream out) {
		this(out, false);
	}
	
	/**
	 * Initializes the stream with the given OutputStream as
	 * destination.
	 * 
	 * @param out destination
	 * @param encoded true for xml and gzip encoding
	 */
	public TransmissionOutputStream(OutputStream out, boolean encoded) {
		super(out);			
		bufout = new BufferedOutputStream(out);
		if(encoded) {
			try {
				gzipout = new GZIPOutputStream(bufout);
			} catch (IOException e) {			
				e.printStackTrace();
			}		
			xmlenc = new XMLEncoder(gzipout);
		} else {
			try {
				oout = new ObjectOutputStream(bufout);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Adds a new Transmitable object to the stream
	 * @param t
	 * @throws IOException
	 */
	public void write(Transmittable t) throws IOException {
		if(xmlenc != null) {
			xmlenc.writeObject(t);
		} else {
			oout.writeObject(t);
		}
	}
	
	/**
	 * Adds a new Response object to the stream
	 * @param r
	 * @throws IOException
	 */
	public void write(Response r) throws IOException {
		if(xmlenc != null) {
			xmlenc.writeObject(r);
		} else {
			oout.writeObject(r);
		}
	}
	
	/**
	 * @see DataOutputStream#flush()
	 */
	@Override
	public void flush() throws IOException {
		if(xmlenc != null) {
			xmlenc.flush();
		} else {
			oout.flush();
		}
		super.flush();
	}
	
	/**
	 * @see DataOutputStream#close()
	 */
	@Override
	public void close() throws IOException {
		if(xmlenc != null) {
			xmlenc.flush();
			xmlenc.close();
		} else {
			oout.close();
		}
		super.close();
	}

}
